#!/usr/bin/env bash

pushd $(dirname $(which $0)) 1>/dev/null
source libs/include.sh
include "libs/auto_update.sh"
include "libs/changelog.sh"
include "libs/database.sh"
include "libs/docker.sh"
include "libs/ohos.sh"
include "libs/output.sh"
include "libs/regex.sh"
include "libs/hdc.sh"
include "libs/zenity.sh"

include "commands/cc.sh"
include "commands/config.sh"
include "commands/docker.sh"
include "commands/git.sh"
include "commands/hdc.sh"
include "commands/repo.sh"
include "commands/utils.sh"
popd 1>/dev/null

# ohos_tool.option -h, --help : 打印本命令的帮助信息
function ohos_tool-h()
{
    ohos_tool--help
}

function ohos_tool--help()
{
    cd $OHOS_TOOL
    echo "用法: $(cctl b)ohos-tool [仓库名] [选项]$(cctl 0)"
    echo "      $(cctl b)ohos-tool [仓库名] 命令 [命令的选项]$(cctl 0)"

    database:global_load
    printf "\n当前可用仓库名:$(cctl y)"
    for (( i = 0; i < $(database:global_get repo_number); i++ )); do
        printf " $(database:global_array_get repo_name $i),"
    done
    printf "\b $(cctl 0)\n"

    printf "\n选项:\n"
    local line
    while read line; do
        line="${line//# ohos_tool.option }"
        local option="${line// : */}"
        local comment="${line//* : /}"
        printf "    $(cctl g)%-30s$(cctl 0) $(cctl c)%s$(cctl 0)\n" "$option" "$comment"
    done <<< $(cat ohos-tool | egrep "^# ohos_tool.option ")

    echo -e "\n命令:"
    local result=$(find commands/ -type f | sort | xargs cat | egrep "^#help.cmd")

    echo "$result" | while read str; do
        str="${str:10}"
        local cmd="${str// : */}"
        local comment="${str//* : /}"
        printf "    $(cctl g)%-30s$(cctl 0) $(cctl c)%s$(cctl 0)\n" "$cmd" "$comment"
    done

    return 0
}

### 用来解析仓库
# @param $1: 疑似的仓库名
# @return 解析失败时返回1, 解析出错时返回2, 其他错误返回3
function ohos_tool:parse_repo_with_name()
{
    local _repo_name="$1"

    # $_repo_name 是一个仓库名
    [[ "$_repo_name" =~ (^${regex_id}$) ]] || return 1

    # 从数据库中找 $_repo_name 这个仓库名
    local i
    for (( i = 0; i < $(database:global_get repo_number); i++ )); do
        local repo_name="$(database:global_array_get repo_name $i)"
        [ "$repo_name" == "$_repo_name" ] || continue
        local repo_path="$(database:global_array_get repo_path $i)"
        ohos:define_repo_data "$repo_name" "$repo_path" || return 3
    done

    if [ "$(ohos:get_repo_name)" == "" ]; then
        # 从数据库中找不到 $_repo_name 这个仓库名
        local _repo_path="${!_repo_name}"
        if [ "$_repo_path" == "" ]; then
            echo "未知的仓库名: $_repo_name"
            return 2
        fi

        ohos:define_repo_data "$_repo_name" "$_repo_path" || return 3
    fi
    return 0
}

### 用来解析仓库
# @param $1: 疑似的仓库名
# @return 解析成功时返回0, 解析失败时返回1, 其他错误返回3
function ohos_tool:parse_repo_without_name()
{
    local tmp_repo_name tmp_repo_path _repo_name
    # 试图用当前路径匹配
    for _repo_name in $(sed 's/;/\n/g' <<< $ohos_repos); do
        # 仓库名必须是一个标识符
        [[ "$_repo_name" =~ (^${regex_id}$) ]] || continue

        local _repo_path="${!_repo_name}"

        # 仓库路径必须是真实路径
        realpath "$_repo_path" 1>/dev/null 2>&1 || continue

        _repo_path="$(realpath "$_repo_path")"

        # 仓库路径必须和执行命令所在的路径前缀重合
        [ "${COMMAND_CURDIR:0:${#_repo_path}}" == "${_repo_path}" ] || continue

        # 在诸多符合条件的仓库中选择路径重合最多的
        (( ${#_repo_path} > ${#tmp_repo_path} )) || continue

        tmp_repo_name="$_repo_name"
        tmp_repo_path="$_repo_path"
    done

    if [ "$tmp_repo_name" == "" ]; then
        # 在 $ohos_repos 中没找到符合条件的仓库
        local i
        for (( i = 0; i < $(database:global_get repo_number); i++ )); do
            local _repo_path="$(database:global_array_get repo_path $i)"

            [ "${COMMAND_CURDIR:0:${#_repo_path}}" == "${_repo_path}" ] || continue
            (( ${#_repo_path} > ${#tmp_repo_path} )) || continue

            tmp_repo_name="$(database:global_array_get repo_name $i)"
            tmp_repo_path="$_repo_path"
        done
    fi

    [ "$tmp_repo_name" != "" ] || return 1
    ohos:define_repo_data "$tmp_repo_name" "$tmp_repo_path" || return 3
}

### 解析ohos_tool的命令
function ohos_tool:parse_command()
{
    arguments $*
    ohos_tool_command="$(arguments:get_now)"
    arguments:next
    if ! [[ "$ohos_tool_command" =~ (^${regex_id}@${regex_id}$) ]]; then
        echo "$ohos_tool_command不是命令"
        return 1
    fi

    ohos_tool_command_func="dynamic_cmd:${ohos_tool_command//@/:}"
    if ! declare -f $ohos_tool_command_func 1>/dev/null; then
        echo "$ohos_tool_command不存在"
        return 1
    fi

    arguments:skip_all
    local args=($(arguments:get_skipped))
    arguments:destroy

    arguments $*
    dynamic_cmd:parse_option "${args[*]}"
    local retval="$?"
    if [ "$retval" == "1" ]; then
        echo "解析${ohos_tool_command}命令失败"
        return 1
    elif [ "$retval" == "2" ]; then
        return 0
    fi

    args=($(arguments:get_skipped))
    arguments:destroy

    ohos:define_command_data
    $ohos_tool_command_func ${args[*]}
}

# ohos_tool.option -v, --version : 打印本命令的版本信息
function ohos_tool-v()
{
    ohos_tool--version
}

function ohos_tool--version()
{
    echo "version: $(git log --oneline | wc -l)"
}

### 解析ohos_tool的选项
function ohos_tool:parse_option()
{
    arguments $*
    while arguments:have_next; do
        local option=$(arguments:get_now)
        arguments:next

        local func="ohos_tool$option"
        if ! declare -f $func 1>/dev/null; then
            echo "${option}不存在"
            continue
        fi
        $func
    done
    arguments:destroy
}

function dynamic_cmd:help:print_option()
{
    local line=$1
    line="${line//# *.option }"
    local option="${line// : */}"
    local comment="${line//* : /}"
    printf "    $(cctl g)%-30s$(cctl 0) $(cctl c)%s$(cctl 0)\n" "$option" "$comment"
}

### 打印动态命令的帮助
function dynamic_cmd:help()
{
    local line

    cd $OHOS_TOOL
    local result="$(find commands/ -type f | xargs cat | egrep "^#help.cmd.*$ohos_tool_command")"
    result="${result:10}"
    result="${result// : */}"
    local cmd="${result// */}"
    echo "用法: $(cctl b)ohos-tool [仓库名] $result [命令的选项]$(cctl 0)"

    local str="$(egrep -hr "^#help.cmd.*$ohos_tool_command")"
    str="${str:10}"
    local comment="${str//* : /}"
    printf "\n作用: $(cctl c)%s$(cctl 0)\n" "$comment"

    printf "\n命令的选项:\n"

    dynamic_cmd:help:print_option "# dynamic.option --help : 打印命令帮助信息"

    # dynamic.option
    while read line; do
        [ "$line" != "" ] || continue
        line="${line//.*/}"
        line="${line//* /}"
        dynamic_cmd:help:print_option "$(egrep -hr "^# dynamic.option $line ")"
    done <<< $(egrep -hr "option.list.*$ohos_tool_command")

    # $ohos_tool_command.option
    while read line; do
        [ "$line" != "" ] || continue
        dynamic_cmd:help:print_option "$line"
    done <<< $(egrep -hr "^# $ohos_tool_command.option ")

    printf "\n命令的别名:\n"
    while read line; do
        line="${line:11}"
        local alias_name="${line// : */}"
        local alias_cmd="${line//* : /}"
        echo "    $(cctl g)$alias_name$(cctl c) = ohos-tool $alias_cmd$(cctl 0)"
    done <<< $(egrep -hr "^#alias.cmd.*$cmd")

    echo
}

### 解析动态命令的选项
# @return 成功时为0, 选项执行失败为1, 打印帮助为2
function dynamic_cmd:parse_option()
{
    arguments $*
    while arguments:have_next; do
        local option=$(arguments:get_now)
        if arguments:is_option; then
            arguments:next
            if [ "$option" == "-h" ] || [ "$option" == "--help" ]; then
                dynamic_cmd:help
                return 2
            fi

            cd $OHOS_TOOL
            local func="dynamic_option:$option"
            if declare -f $func 1>/dev/null; then
                if egrep -r "^# ${option}.option.list: .*$ohos_tool_command" 1>/dev/null 2>&1; then
                    $func
                    continue
                fi
            fi
            cd - 1>/dev/null

            func="$ohos_tool_command_func${option}"
            if ! declare -f $func 1>/dev/null; then
                echo "${option}不存在"
                continue
            fi

            $func || return 1
        else
            arguments:skip
            continue
        fi
    done
}

function ohos_tool:main()
{
    ohos:define_global_data

    if ! arguments:have_next; then
        ohos_tool--help
        return
    fi

    # 解析仓库
    local _repo_name="$(arguments:get_now)"
    ohos_tool:parse_repo_with_name "$_repo_name"
    local retval="$?"
    if [ "$retval" == "0" ]; then
        arguments:next
    elif [ "$retval" == "1" ]; then
        ohos_tool:parse_repo_without_name
        retval="$?"
        if [ "$retval" == "3" ]; then
            return 1
        fi
    else
        return 1
    fi

    local _option="$(arguments:get_now)"
    arguments:skip_all
    local args=($(arguments:get_skipped))
    arguments:destroy

    if [[ "$_option" =~ (^-[a-zA-Z0-9=-]+$) ]]; then
        ohos_tool:parse_option "${args[*]}"
    else
        ohos_tool:parse_command "${args[*]}"
    fi
}

arguments $*
ohos_tool:main
